#include <fstream>
#include <iostream>
#include <list>
#include <queue>
#include <sstream>
#include <stack>
#include <string>

#include <clang/AST/AST.h>
#include <clang/AST/ASTConsumer.h>
#include <clang/AST/Attr.h>
#include <clang/AST/Expr.h>
#include <clang/AST/RecursiveASTVisitor.h>
// #include <clang/Analysis/CFG.h>
// #include "CFG/CFG.h"
#include "CFG/SACFG.h"

#include <clang/Frontend/ASTConsumers.h>
#include <clang/Frontend/ASTUnit.h>
#include <clang/Frontend/CompilerInstance.h>
#include <clang/Frontend/FrontendActions.h>
#include <clang/Lex/Lexer.h>
#include <clang/Rewrite/Core/Rewriter.h>
#include <clang/Tooling/CommonOptionsParser.h>
#include <clang/Tooling/Tooling.h>
#include <llvm/Support/raw_ostream.h>

#include "CFG/InterProcedureCFG.h"
#include "framework/BasicChecker.h"
#include "framework/Report.h"

using namespace clang;
using namespace llvm;
using namespace clang::driver;
using namespace clang::tooling;
using namespace std;

struct Warning
{
    FunctionDecl *FD;
    unsigned beginLine;
    unsigned beginCol;
    unsigned endLine;
    unsigned endCol;
    int stmtNums;
    string fileName;

    void report()
    {
        cout << "Function Name : " << FD->getNameAsString() << ", total : " << stmtNums << ", "
             << " from " << beginLine << " to " << endLine << " " << endl;
    }
};

struct OSAPI
{
    unsigned line;
    unsigned col;
    int visitNum;
    string fileName;
};

class FrequentProcessSwitchChecker : public BasicChecker
{
private:
    ASTResource *resource;
    ASTManager *manager;
    CallGraph *call_graph;
    Config *configure;

public:
    FrequentProcessSwitchChecker(ASTResource *_resource, ASTManager *_manager, CallGraph *_call_graph, Config *_configure) : BasicChecker(_resource, _manager, _call_graph, _configure), resource(_resource), manager(_manager), call_graph(_call_graph), configure(_configure){

                                                                                                                                                                                                                                                          };
    void check();

private:
    void getEntryFunc();
    void readConfig();
    void analyse();
    vector<string> parse(string funcs);
    ASTFunction *entryFunc;
    InterProcedureCFG *icfg;
    int limit;
    int threshold;
    vector<string> funcs;
};
